package ourfilter;

import interfaces.Readable;
import interfaces.Writeable;

import java.io.StreamCorruptedException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Currency;
import java.util.LinkedList;
import java.util.StringTokenizer;

import pipes.Pipe;
import TransferObjekts.Line;
import TransferObjekts.Word;
import filter.AbstractFilter;

public class CircularShiftFilter extends AbstractFilter<Word, Line> {
	private Readable<Word> in;
	private Writeable<Line> out;
	private Word prevWord = null;
	private LinkedList<Line> lineBuffer = new LinkedList<Line>();
	private boolean endOfStreamHasReached = false;
	private String curLine = "";

	public CircularShiftFilter(Pipe<Word> in, Pipe<Line> out) throws InvalidParameterException {
		super(in, out);
		in.setOut(this);
		out.setIn(this);
		this.in = in;
		this.out = out;
	}

	private Line buildLine() throws StreamCorruptedException {
		String line = "";
		Word currentWord = in.read();
		if (prevWord == null) {
			prevWord = currentWord;
		}

		while (currentWord.getLineNumber() == prevWord.getLineNumber()) {
			line += currentWord.getWord() + " ";
			currentWord = in.read();
			if (currentWord == null) {
				endOfStreamHasReached = true;
				return new Line(line, prevWord.getLineNumber());
			}
		}
		prevWord = currentWord;

		return new Line(line, prevWord.getLineNumber());
	}

	@Override
	public Line read() throws StreamCorruptedException {
		if (!endOfStreamHasReached) {
			Line line = buildLine();
	
			prozess(line, line.getLineNumber());
		}
		return lineBuffer.poll();
	}

	private void prozess(Line l, int lineNumber) {
		StringTokenizer tokenizer = new StringTokenizer(l.getLine());
		ArrayList<String> token = new ArrayList<String>();
		while (tokenizer.hasMoreElements()) {
			token.add(tokenizer.nextToken());
		}

		for (int i = 0; i < token.size(); i++) {
			String line = "";
			for (int k = 0; k < token.size(); k++) {
				line += token.get(k) + " ";
			}
			token.add(token.get(0));
			token.remove(0);
			lineBuffer.add(new Line(line.trim(), lineNumber));
		}
	}

	private int i = 0;

	@Override
	public void write(Word word) throws StreamCorruptedException {
		if (word != null) {
			if (prevWord == null) {
				prevWord = word;
			}
			if (word.getLineNumber() == 2475) {
				int t = 0;
				t++;
			}
			if (prevWord.getLineNumber() == word.getLineNumber()) {
				curLine += word.getWord() + " ";
				prevWord = word;
			} else {
				Line line = new Line(curLine, prevWord.getLineNumber());
				prevWord = word;
				curLine = prevWord.getWord() + " ";

				prozess(line, line.getLineNumber());
				out.write(lineBuffer.poll());
			}
		} else {
			prozess(new Line(curLine, prevWord.getLineNumber()), prevWord.getLineNumber());
			lineBuffer.add(null);
			int curSize = lineBuffer.size();
			for (int i = 0; i < curSize; i++) {
				out.write(lineBuffer.poll());
			}
		}
	}

	@Override
	public void run() {

	}

}
